/**********************************************************************
                     ctgpick.c

written by IL
seriously edited by CAS

Displays keyset and contains submenus and routines
see also: searchroutines contains the Search Command menu
see also: getlist creates the initial list

6/25/04 - cari fixed all the "Remove remarks"
**********************************************************************/
#include "fpp.h"
#include "seq.h"
#include <string.h>
#include <gtk/gtkwidget.h>  /*fred 3/5/03*/
extern void  settime();
extern int max_clonesz, max_markersz, max_seqsz; /* defined in fpc_load.c */
extern char clone_marks[CLONE_MARKER_MAX][MARKER_SZ+1];  /*fred 6/13/03*/
extern int removemarks();  /*fred 6/13/03*/
extern void lowerstring();
extern void sortoutmarkersman();
extern void markersinctgcount();
extern void clearallmaps();
extern int unbury();
extern void deleteclone();

void updateproj(void);
void displaymarker();
void addfpccomment(void);
void rmfpccomment(void);
void MRKaddfpccomment(void); /*fred 12/23/02*/
void MRKrmfpccomment(void);  /*fred 12/23/02*/
void remove_keyset_markers(void);  /*fred 6/13/03*/
void exportctglist(void);
void removefromctgs(void);  /*efriedr 3/15/02*/
void movetoctgN(void);  /*cari 12/30/03 */
void cancelclones(void);    /*efriedr 10/23/02*/
void addclonetomarker();
void appendCloneToMarkerList(int cloneindex); /*fred 12/21/02*/

extern int NewSearchClass;
extern GtkWidget *ctg_window;  /*fred 3/5/03*/

/*fred 12/23/02*/
static int exact_match = 1;
static int substr_match = 0;
static int exactArc=0;
static int substrArc=0;

FPC_SEQ* lastpickedseq;

BOOL setpage(float *y)
{
  int w,h,pagebefore;
  float num;

  pagebefore = page;
  graphFitBounds(&w,&h);
  *y -= 2.0; /* take away top bit*/
  h -=4.0;
  if(*y<=0.0)
    page = 0;
  else{
    num = *y/(float)h;
    num = num*(float)(maxpage+1);
    page= (int)num;
  }
  if((*y < (boxstart-2.0)) && page == pagebefore && page != 0)
    page--;
  else if((*y > (boxstart-2.0)) && page == pagebefore && page != maxpage)
    page ++;
  if(page > maxpage)
    page = maxpage;
  return TRUE;
}

void keybanddrag(float *x, float *y, BOOL isUP)
/* This routine enable the scrollbar to be dragged for the fp map */
{

  *x =  0.5; /* x is set to the middle */

  if(isUP) /* after scrolling has finished */
    {
      if(setpage(y))                 /* if shifted (always true */
	displaykeyset(1);       /* then redraw the list*/
    }

}

void ctgpick(int box, double x, double y)
{
  int ctg;
  struct list *p;
  BOOL notfound;

  if (NewSearchClass) {
      printf("Keyset was not of current class so could not pick entity. Changed class.\n");
      getlist();
      displaykeyset(1);
      return;
  }
  ctg = -1;
  if(!box) return;

  if(box==keysetband){
      if(maxpage != 0)
	graphBoxDrag(box, keybanddrag);
      return;
  }
  if(box==upkey){
      page--;
      if(page < 0)
	page =0;
      displaykeyset(1);
      return;
  }
  if(box==downkey){
      page++;
      if(page > maxpage)
	page = maxpage;
      displaykeyset(1);
      return;
  }
  p= listroot;
  notfound = TRUE;
  while(p!=NULL && notfound){
      if(box== p->box){
	notfound = FALSE;
	break;
      }
      p=p->next;
  }
  if(notfound)
      printf("FPC ERROR: Box picked not found\n");
  else{
      if(editmarkerstatus == 1){
         if(classctg==CLONECLASS)   /*fred 12/21/02*/
	    appendCloneToMarkerList(p->index);
      }
      if( (classctg==SEQCLASS && lastpickedseq == p->seq) ||
            (classctg != SEQCLASS && lastpicked==p->index)){
	if(classctg == CTGCLASS){
	  ctgdisplay(p->index);
          gdk_window_raise(ctg_window->window);
	}
	else if(classctg == CLONECLASS){
	  displayclone(p->index);
	}
	else if(classctg == SEQCLASS){
	  displaysequence(p->seq);
	}
	else{
	  displaymarker(p->index);
	}
      }
      else {
	lastpicked = p->index;
    lastpickedseq = p->seq;
	displaykeyset(1);		/* highlight box picked */
      }
  }
}

void quitlist()
{
char temp[NAME_SZ];
  graphDestroy();
  strcpy(temp,chsearchglob);
  strcpy(chsearchglob,"");
  getlist();
  strcpy(chsearchglob, temp);
  menu_main();
}

void displistresize()
{
  /* will need to recalculate the page */
  page = 0;
  displaykeyset(1);
}

void pagedown()
/* This routine increases the page number by 1 i.e. move a page down */
/* and redisplays the list of available contigs */
{

 page++;
 displaykeyset(1);
}

void pageup()
/* This routine decreases the page number by 1 i.e. move a page up */
/* and redisplays the list of available contigs */
{
  page--;
  displaykeyset(1);
}

/*****************************************************************
                     DEF: displaykeyset
****************************************************************/
void displaykeyset(int rc)
/* This routine displays the available contigs page by page */
/* and allows the user to pick one of these */
{
  int x,y,i,total,k;
  BOOL new;
  static MENUOPT menu[] = {
  { quitlist, "Close"},
  { MRKaddfpccomment,"Add Remark"},
  { MRKrmfpccomment,"Remove Remark"},
  { remove_keyset_markers,"Remove Markers"},
  { exportctglist,"Export list"},
  { graphPrint, "Print Screen"}, 
  { 0, 0 } } ;
  static MENUOPT menuclone[] = {
  { quitlist, "Close"},
  { graphPrint, "Print Screen"},
  { addfpccomment,"Add Remark"},
  { rmfpccomment,"Remove Remark"},
  { exportctglist,"Export list"},
  { removefromctgs,"Move to ctg0"},      /*efriedr 3/15/02*/
  { movetoctgN,"Move from ctg0 to ctgN"},     /*cari 12/30/03 */
  { cancelclones,"Cancel clones"},       /*efriedr 10/23/02*/
  { 0, 0 } };
  struct list *p;
  char text[MARKER_SZ+1];
  char str1[80], tmp[30];
  int w,h,numvert,numhoz,ff;
  static int maxperpage,maxsize;
  float xpt,top,bottom,range,boxend;
  
  if (listroot==NULL) {
     displaymess("No list to display");
     return;
  }

  total =0;
  p = listroot;
  while(p!=NULL){
      total++;
      p=p->next;
  }
  if(total==1){
      lastpicked = -1;
      lastpickedseq = 0;	
      if(graphActivate(g2))    /* reset graph */
	graphDestroy();
      if(classctg == CTGCLASS){
	 newctg= TRUE;
	 ctgdisplay(listroot->index);
      }
      else if(classctg == MARKERCLASS){
	  displaymarker(listroot->index);
	  graphPop();
      }
      else if(classctg == SEQCLASS){
	  displaysequence(listroot->seq);
	  graphPop();
      }
      else{
	  displayclone(listroot->index);
	  graphPop();
      }
      /* reset the list */
      getlist();
      return;
  }
  if(graphActivate(g2)){    /* reset graph */
      graphClear();
      new = FALSE;
  }
  else{	                   /* create graph and buttons etc */
      new= TRUE;
      g2 = graphCreate (TEXT_FIT,"Keyset",.2,.2,.4,.3) ;

      graphRegister(PICK, ctgpick) ;
      graphRegister(RESIZE,displistresize); 
      graphMenu (menu) ;
  }
    graphFitBounds(&w,&h);
    if(classctg == CLONECLASS){
      maxsize = max_clonesz+2;
      numvert = (int)((h-4)/2);
      numhoz =(int)(w-4)/maxsize;
      maxperpage = numhoz*numvert;
    }
    else if(classctg == MARKERCLASS){
      maxsize = max_markersz+2;
      numvert = (int)((h-4)/2);
      numhoz =1 + (int)(w-4)/maxsize;
      maxperpage = numhoz*numvert;
    }
    else if(classctg == SEQCLASS){
      maxsize = max_seqsz+2;
      numvert = (int)((h-4)/2);
      numhoz =(int)(w-4)/maxsize;
      maxperpage = numhoz*numvert;
    }
    else{
      sprintf(tmp,"%d",max_contig);
      maxsize = strlen(tmp)+5; /* CHG 03/08/01 */
      numvert = (int)((h-4)/2);
      numhoz =(int)(w-4)/maxsize;
      maxperpage = numhoz*numvert;
    }
    maxpage = (int)(total/maxperpage);
    
    if(classctg == CTGCLASS)
	sprintf(str1,"Contigs %d  (page %d/%d)",total,page+1,maxpage+1);
    else if(classctg == CLONECLASS)
	sprintf(str1,"Clones %d (page %d/%d)",total,page+1,maxpage+1);
    else if(classctg == SEQCLASS)
	sprintf(str1,"Sequences %d (page %d/%d)",total,page+1,maxpage+1);
    else
	sprintf(str1,"Markers %d (page %d/%d)",total,page+1,maxpage+1);

    graphRetitle(str1);
    if (rc==0) 
	graphText("Search failed", 3.0, 1.0); 

    top = 2.0;
    bottom = (float)h -2.0;
    range = (float)h - 2.0 - top;
    if(maxpage==0){
      boxstart =1.0;
      boxend = bottom;
    }
    else{
      if(page==0)
	boxstart = top;
      else
	boxstart = ((( (float)page/((float)maxpage+1.0) ))*range) + top;      
      if(maxpage == page)
	boxend = bottom;
      else
	boxend = ((( ((float)page+1.0)/((float)maxpage+1.0) ))*range) + top;
    }

    xpt = 1.0;
    graphLine(xpt,top,xpt,bottom); 
    
    if((boxend - boxstart) < 0.4)
      boxend = boxstart + 0.4;
    keysetband = graphBoxStart();
    graphRectangle(xpt-0.5,boxstart,xpt+0.5,boxend);
    graphBoxEnd();
    graphBoxDraw(keysetband,BLACK,GREEN);
    upkey = graphBoxStart();
    graphRectangle(xpt-0.5,top,xpt+0.5,top-1.0);
    graphLine(xpt-0.5,top,xpt,top-1.0);
    graphLine(xpt,top-1.0,xpt+0.5,top);
    graphBoxEnd();
    graphBoxDraw(upkey,BLACK,GREEN);
    
    downkey = graphBoxStart();
    graphRectangle(xpt-0.5,bottom,xpt+0.5,bottom+1.0);
    graphLine(xpt-0.5,bottom,xpt,bottom+1.0);
    graphLine(xpt,bottom+1.0,xpt+0.5,bottom);
    graphBoxEnd();
    graphBoxDraw(downkey,BLACK,GREEN);

    if(classctg == CLONECLASS)
      graphMenu(menuclone);
    else
      graphMenu(menu);

    x = 5; /* start x pos */
    y = 1; /* start y pos */
      
    p = listroot;  /* go ahead "page" pages */
    for(i=0;i<page;i++){
      k=1;
      while(p!=NULL && k<=maxperpage){
	k++;
	p->box = 0;
	p=p->next;
      }
    }
    k=1;
    i=1;
    
    ff =(numvert+1)*2; 
    while(k<=maxperpage){ 
      if(p!=NULL){
	y += 2;
	if(y>=ff){
	  y= 3;
	  x +=maxsize; 
	}
	if(classctg == CTGCLASS)
	  sprintf(text,"ctg%d",p->index);
	else if(classctg == CLONECLASS){ /* CLONE_SZ */
	  sprintf(text,"%-15s",arrp(acedata,p->index,CLONE)->clone);
	}
	else if(classctg == SEQCLASS){ 
	  sprintf(text,"%-15s",p->seq->name);
	}
	else                             /* MARKER_SZ */
	  sprintf(text,"%-16s", arrp(markerdata,p->index,MARKER)->marker);
	p->box = graphBoxStart();
	graphText(text, x,y ); /* write contig */     
	graphBoxEnd();
    if (classctg == SEQCLASS) {
	  if(p->seq == lastpickedseq)  /* if selected then highlight it */
	    graphBoxDraw(p->box,WHITE,BLACK);
    }
    else {
	  if(p->index == lastpicked)  /* if selected then highlight it */
	    graphBoxDraw(p->box,WHITE,BLACK);
    }
	p=p->next;
      }
      k++;
    }
  
  graphRedraw();
}

void commentset(char *temp)
{
  if(dataloaded){    
    strcpy(commentglob,temp);
    addfpccomment();
  }
}
void commentset2(char *temp)
{
  if(dataloaded){    
    strcpy(commentglob,temp);
    rmfpccomment();
  }
}

void add_fp_comment()
{
  struct remark *fpc;
  struct list *q;
  CLONE *clone;
  int cnt=0;

  for (q = listroot; q!=NULL; q=q->next)
  {
    cnt++;
    clone = arrp(acedata,q->index,CLONE);
    fpc = clone->fp_remark;
    if(fpc == NULL){
      clone->fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = clone->fp_remark;
    }
    else{
      while(fpc->next !=NULL)
	fpc=fpc->next;
      fpc->next = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = fpc->next;
    }
    fpc->next = NULL;
    strcpy(fpc->message,commentglob);
    settime(&clone->modified_date);
  }
  graphDestroy();
  printf("Add %d fp_remarks\n",cnt);
}

void MRKadd_comment()
{
  struct remark *fpc;
  struct list *q;
  MARKER *marker;

  for (q = listroot; q!=NULL; q=q->next) 
  {
    marker = arrp(markerdata,q->index,MARKER);
    fpc = marker->remark;
    if(fpc == NULL){
      marker->remark = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = marker->remark;
    }
    else{
      while(fpc->next !=NULL)
	fpc=fpc->next;
      fpc->next = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = fpc->next;
    }
    fpc->next = NULL;
    strcpy(fpc->message,commentglob);
    settime(&marker->modified_date);
  }
  graphDestroy();
}

void MRKremove_comment(){
  struct remark *fp,*prev;
  struct list *q;
  MARKER *marker;
  int cnt=0;
  char tmp[300];

  lowerstring(rmcommentglob);
  for (q = listroot; q!=NULL; q=q->next) 
  {
     marker = arrp(markerdata,q->index,MARKER);
     prev = NULL;
     for (fp = marker->remark; fp != NULL; fp = fp->next)
     {
        strcpy(tmp, fp->message);
        lowerstring(tmp);
        if((exact_match && strcmp(tmp,rmcommentglob)==0) ||
           (substr_match && strstr(tmp,rmcommentglob)!=NULL))
        {
            cnt++;
	    if(fp->next == NULL){ /* last */
               if (prev == NULL) marker->remark = NULL;
               else prev->next = NULL;
	    }
            else if (prev == NULL) { /* first */
               marker->remark = fp->next;
            }
	    else{
	       prev->next = fp->next;
	    }
        }
        else prev = fp;
     }    
  }
  printf("Remove remark from %d markers.\n",cnt);
  graphDestroy();
}

void add_comment()
{
  struct remark *fpc;
  struct list *q;
  CLONE *clone;
  int cnt=0;

  for (q=listroot; q!=NULL; q=q->next){
    clone = arrp(acedata,q->index,CLONE);
    fpc = clone->remark;
    if(fpc == NULL){
      clone->remark = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = clone->remark;
    }
    else{
      while(fpc->next !=NULL)
	fpc=fpc->next;
      fpc->next = (struct remark *)messalloc((sizeof(struct remark)));
      fpc = fpc->next;
    }
    fpc->next = NULL;
    strcpy(fpc->message,commentglob);
    settime(&clone->modified_date);
    cnt++;
  }
  graphDestroy();
  printf("Add remark to %d clones.\n",cnt);
}

void remove_fp_comment()
{
  struct remark *fp,*prev;
  struct list *q;
  CLONE *clone;
  int cnt=0;
  char tmp[300];

  lowerstring(rmcommentglob);
  for (q = listroot; q!=NULL; q=q->next) 
  {
     clone = arrp(acedata,q->index,CLONE);
     prev = NULL;
     for (fp = clone->fp_remark; fp != NULL; fp = fp->next)
     {
        strcpy(tmp, fp->message);
        lowerstring(tmp);
        if((exact_match && strcmp(tmp,rmcommentglob)==0) ||
           (substr_match && strstr(tmp,rmcommentglob)!=NULL))
        {
            cnt++;
	    if(fp->next == NULL){ /* last */
               if (prev == NULL) clone->fp_remark = NULL;
               else prev->next = NULL;
	    }
            else if (prev == NULL) { /* first */
               clone->fp_remark = fp->next;
            }
	    else{
	       prev->next = fp->next;
	    }
        }
        else prev = fp;
     }    
  }
  printf("Remove fp_remark from %d clones.\n",cnt);
  graphDestroy();
}

void remove_comment(){
  struct remark *fp,*prev;
  struct list *q;
  CLONE *clone;
  int cnt=0;
  char tmp[300];

  lowerstring(rmcommentglob);
  for (q = listroot; q!=NULL; q=q->next) 
  {
     clone = arrp(acedata,q->index,CLONE);
     prev = NULL;
     for (fp = clone->remark; fp != NULL; fp = fp->next)
     {
        strcpy(tmp, fp->message);
        lowerstring(tmp);
        if((exact_match && strcmp(tmp,rmcommentglob)==0) ||
           (substr_match && strstr(tmp,rmcommentglob)!=NULL))
        {
            cnt++;
	    if(fp->next == NULL){ /* last */
               if (prev == NULL) clone->remark = NULL;
               else prev->next = NULL;
	    }
            else if (prev == NULL) { /* first */
               clone->remark = fp->next;
            }
	    else{
	       prev->next = fp->next;
	    }
        }
        else prev = fp;
     }    
  }
  printf("Remove remark from %d clones.\n",cnt);
  if (graphActivate(gcomment)) graphDestroy();
}

void remove_both_comment(){
  remove_fp_comment();
  remove_comment();
}

void MRKpickmatchtype(int box, double x, double y){
  if(box==0) return;
  else if(box==exactArc){
     if(!exact_match){
        exact_match = !exact_match;
        substr_match = !substr_match;
     }
  }
  else if(box==substrArc){
     if(!substr_match){
        exact_match = !exact_match;
        substr_match = !substr_match;
     }
  }
  MRKrmfpccomment();
}
  
void pickmatchtype(int box, double x, double y){
  if(box==0) return;
  else if(box==exactArc){
     if(!exact_match){
        exact_match = !exact_match;
        substr_match = !substr_match;
     }
  }
  else if(box==substrArc){
     if(!substr_match){
        exact_match = !exact_match;
        substr_match = !substr_match;
     }
  }
  rmfpccomment();
}
  
void MRKrmfpccomment()
{
  int variableArc=0;
  if(graphActivate(gcomment)){
    graphClear();
    graphPop();
  }
  else{
    gcomment = graphCreate (TEXT_FIT,"Remove Remark",.2,.2,.3,.2) ; 
    graphRegister (PICK, MRKpickmatchtype);
  }
  graphText("Ten chars Max",2.0,2.0);
  graphTextEntry(rmcommentglob, 10, 20.0, 2.0, commentset2);      

  graphButton("Remove Remark",MRKremove_comment,2.0,4.0);

  graphText("Exact match",4.0,6);
  exactArc = graphBoxStart();
  graphArc(2.0, 6+0.5, 0.7, 0, 360);
  if (exact_match) graphFillArc(2.0, 6+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(variableArc, BLACK, TRANSPARENT);

  graphText("Substring",20.0,6);
  substrArc = graphBoxStart();
  graphArc(18.0, 6+0.5, 0.7, 0, 360);
  if (substr_match) graphFillArc(18.0, 6+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(variableArc, BLACK, TRANSPARENT);

  graphButton("Close",graphDestroy,2.0,8.0);
  graphRedraw();
}

void MRKaddfpccomment()
{

  if(graphActivate(gcomment)){
    graphClear();
    graphPop();
  }
  else{
    gcomment = graphCreate (TEXT_FIT,"Add Remark",.2,.2,.3,.2) ; 
  }
  graphText("Ten chars Max",2.0,2.0);
  graphTextEntry(commentglob, 10, 20.0, 2.0, commentset);      

  graphButton("Add Remark",MRKadd_comment,2.0,4.0);
  graphButton("Close",graphDestroy,2.0,6.0);
  graphRedraw();
}

void remove_keyset_markers(){
  Array markerdata2;
  int i, j, c, removed=0;
  MARKER marker;
  CLONE *clp;
  struct markertop *mptr;
  struct list *q;
  int marker_in_keyset=1;
 
  if(!graphQuery("This will remove the Markers in the keyset from the project. Continue? "))
    return;
  markerdata2 = arrayCreate(arrayMax(markerdata),MARKER);
  j = removed = 0;
  for(i=0;i<arrayMax(markerdata);i++){
    marker = arr(markerdata,i,MARKER);
/*See if marker is in keyset*/
    marker_in_keyset=FALSE;
    q = listroot;
    while(q!=NULL){
      if(q->index==i){
        marker_in_keyset=TRUE;
        break;
      }
      q=q->next;
    }
    if(marker_in_keyset){
      removed++;
      printf("Remove marker %s\n",marker.marker);
      for (c=0; c<arrayMax(acedata); c++) {
	  clp = arrp(acedata, c, CLONE);
	  for (mptr = clp->marker; mptr != NULL; mptr = mptr->nextmarker) {
	     if(strcmp(mptr->marker,marker.marker)==0) {
		strcpy(clone_marks[0], mptr->marker);
		removemarks(1, c);
		break;
	     }
	  }
      }
    }
    else {
       array(markerdata2,j,MARKER) = marker;
       j++;
    }
  }
  printf("\nRemoved total of %d markers.\n", removed);
  arrayDestroy(markerdata);
  markerdata = markerdata2;
  sortoutmarkersman();
  markersinctgcount();
  clearallmaps();
  update=TRUE;
}

void rmfpccomment()
{
  int variableArc=0;
  if(graphActivate(gcomment)){
    graphClear();
    graphPop();
  }
  else{
    gcomment = graphCreate (TEXT_FIT,"Remove Remark",.2,.2,.3,.2) ; 
    graphRegister (PICK, pickmatchtype);
  }
  graphText("Ten chars Max",2.0,2.0);
  graphTextEntry(rmcommentglob, 10, 20.0, 2.0, commentset2);      

  graphButton("Remove Fp_remark",remove_fp_comment,2.0,4.0);
  graphButton("Remove Remark",remove_comment,2.0,6.0);
  graphButton("Remove Both",remove_both_comment,2.0,8.0);

  graphText("Exact match",4.0,10);
  exactArc = graphBoxStart();
  graphArc(2.0, 10+0.5, 0.7, 0, 360);
  if (exact_match) graphFillArc(2.0, 10+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(variableArc, BLACK, TRANSPARENT);

  graphText("Substring",20.0,10);
  substrArc = graphBoxStart();
  graphArc(18.0, 10+0.5, 0.7, 0, 360);
  if (substr_match) graphFillArc(18.0, 10+0.5, 0.4, 0, 360);
  graphBoxEnd();
  graphBoxDraw(variableArc, BLACK, TRANSPARENT);

  graphButton("Close",graphDestroy,2.0,12.0);
  graphRedraw();
}

void addfpccomment()
{
  if(graphActivate(gcomment)){
    graphClear();
    graphPop();
  }
  else{
    gcomment = graphCreate (TEXT_FIT,"Add Remark",.2,.2,.3,.2) ; 
  }
  graphText("Ten chars Max",2.0,2.0);
  graphTextEntry(commentglob, 10, 20.0, 2.0, commentset);      

  graphButton("Add Fp_remark",add_fp_comment,2.0,4.0);
  graphButton("Add Remark",add_comment,2.0,6.0);
  graphButton("Close",graphDestroy,2.0,8.0);
  graphRedraw();
}

void exportctglist()
{
  struct list *p;
  FILE *fpace;
  int graphQueryOpen();

  /* open file to dump keyset to*/
  if(!( fpace = (FILE *)graphQueryOpen(mergedir,
        mergefile,"txt","w","txt filename"))){
    printf("Error opening file\n");
    return;
  }
  printf("Export list to file %s.txt\n",mergefile);
  if(listroot!=NULL){
    p = listroot;
    if(classctg == CTGCLASS){
      while(p!=NULL){
	fprintf(fpace,"ctg%d\n",p->index);
	p=p->next;
      }
    }
    else if(classctg == CLONECLASS){
      while(p!=NULL){
	fprintf(fpace,"%s\n",arrp(acedata,p->index,CLONE)->clone);
	p=p->next;
      }
    }
    else if(classctg == CLONECLASS){
    }
    else{
      while(p!=NULL){
	fprintf(fpace,"%s\n",arrp(markerdata,p->index,MARKER)->marker);
	p=p->next;
      }
    }   
  }
  fclose(fpace);
}

/************************************************************8
                DEF: removefromctgs
*************************************************************/
void removefromctgs(){      /*efriedr 3/15/02  Move keyset clones to ctg 0.*/
   struct list *p;
   CLONE *clp;
   void move_selected(int from,int result,int distance);
   int cnt=0;

   if(graphQuery("Do you wish to move all clones in keyset to ctg0 (i.e. make them singletones)? "))
   {
      if(listroot!=NULL){
         p=listroot;
         if(classctg==CLONECLASS){
            while(p!=NULL){
               clp=arrp(acedata,p->index,CLONE);
               if(clp->parent != -1) unbury(p->index);
               clp->selected=1;
               move_selected(clp->ctg,0,0);
               p=p->next;
               clp->selected=0;
               cnt++;
            }
         }
      }
   }
printf("Move %d clones to ctg0\n",cnt);
}
/************************************************************8
                DEF: movetoctgN 
*************************************************************/
void movetoctgN(){      
   struct list *p;
   CLONE *clp;
   void move_selected(int from,int result,int distance);
   char str[200];
   int n, cnt=0;

   n = getcontigsmax()+1; 
   if (listroot==NULL || classctg!=CLONECLASS) {
      printf("No clones in keyset\n");
      return;
   } 
   sprintf(str,"Do you wish to move all clones in keyset to ctg%d\n(note: they will have no order, run CB algorithm from contig)",n);
   if(!graphQuery(str)) return;

   for (p=listroot; p!=NULL; p=p->next){
        clp=arrp(acedata,p->index,CLONE);
        if (clp->ctg!=0) {
            printf("Ignore %s - it is in ctg%d\n",clp->clone,clp->ctg);
        }
        else if (clp->fp==NULL) {
            printf("Ignore %s - it has no fingerprints\n",clp->clone);
        }
        else {
            if(clp->parent != -1) unbury(p->index);
            clp->selected=1;
            clp->x=0;
            clp->y= clp->fp->b2;
            cnt++;
         }
   }
   if (cnt>0) move_selected(0,n,0);
   printf("Move %d clones to contig %d\n",cnt,n);
}

/*****************************************************
                DEF: cancelclones
******************************************************/
void cancelclones(){      /*efriedr 10/23/02  Cancel keyset clones*/
   struct list *p;
   CLONE *clp;
   int temp;

   if(graphQuery("Do you wish to cancel all clones in keyset? "))
   {
      temp=clonedisplayed;
      if(listroot!=NULL){
         p=listroot;
         if(classctg==CLONECLASS){
            while(p!=NULL){
               clp=arrp(acedata,p->index,CLONE);
               if(clp->parent != -1) unbury(p->index);
               clonedisplayed=p->index;
               deleteclone();
               p=p->next;
            }
         }
      }
      clonedisplayed=temp;
   }
}
